package top.hmtools.wxmp.core.httpclient;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpHost;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 获取httpclient对象实例的工具
 * @author HyboWork
 *
 */
public class HmHttpClientFactoryHandle {
	
	private final static Logger logger = LoggerFactory.getLogger(HmHttpClientFactoryHandle.class);

	//连接池支持
	
	//ssl支持
	
	//超时时间配置
	
	//设置重试机制
	private static HttpRequestRetryHandler httpRequestRetryHandler;
	
	//ConnectionManager
	private static PoolingHttpClientConnectionManager poolingHttpClientConnectionManager;
	
	//DefaultCookieStore
	
	//DefaultCredentialsProvider
	
	/**
	 * 保持http长连接配置？？
	 */
	private static ConnectionKeepAliveStrategy connectionKeepAliveStrategy ;
	
	//Proxy
	private static List<HttpHost> proxies;
	
	//DefaultRequestConfig，由Builder生成
	private static Builder requestConfigBuilder;
	
	/**
	 * 基于连接池的httpclient创建器
	 */
	private static HttpClientBuilder poolingHttpClientBuilder;

	/**
	 * 简单的自定义httpclient创建器
	 */
	private static HttpClientBuilder simpleHttpClientBuilder;
	
	
	/**
	 * 初始化
	 */
	public static synchronized void init(){
		//初始化基于连接池的连接管理器
		if(poolingHttpClientConnectionManager == null){
			setPoolingHttpClientConnectionManager(200, 20);
		}
		
		
	}
	
	/**
	 * 设置基于连接池的连接管理器
	 * @param maxTotal
	 * @param defaultMaxPerRoute
	 */
	public synchronized static void setPoolingHttpClientConnectionManager(int maxTotal,int defaultMaxPerRoute){
		if(poolingHttpClientConnectionManager == null){
			//设置支持SSL
			SSLContext sslcontext = SSLContexts.createSystemDefault();
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
	        .register("http", PlainConnectionSocketFactory.INSTANCE)
	        .register("https", new SSLConnectionSocketFactory(sslcontext))
	        .build();
			
			poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
		}
		poolingHttpClientConnectionManager.setMaxTotal(maxTotal);
		poolingHttpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
	}
	
	/**
	 * 设置基于连接池的连接管理器
	 * @param poolingHttpClientConnectionManager
	 */
	public static void setPoolingHttpClientConnectionManager(
			PoolingHttpClientConnectionManager poolingHttpClientConnectionManager) {
		HmHttpClientFactoryHandle.poolingHttpClientConnectionManager = poolingHttpClientConnectionManager;
	}
	
	/**
	 * 设置代理列表
	 * @param proxiesHost
	 */
	public static void setProxies(List<HttpHost> proxiesHost) {
		HmHttpClientFactoryHandle.proxies = proxiesHost;
	}
	
	/**
	 * 添加代理信息
	 * @param proxiesHost
	 */
	public synchronized static void addProxies(HttpHost... proxiesHost){
		if(proxiesHost == null || proxiesHost.length<1){
			return;
		}
		
		List<HttpHost> proxiesListParam = Arrays.asList(proxiesHost);
		if(proxies ==null){
			proxies = new ArrayList<HttpHost>();
		}
		proxies.addAll(proxiesListParam);
	}
	
	/**
	 * 设置请求配置创建器
	 * @param socketTimeout
	 * @param connectTimeout
	 * @param ConnectionRequestTimeout
	 */
	public synchronized static void setRequestConfigBuilder(int socketTimeout,int connectTimeout,int ConnectionRequestTimeout){
		if(requestConfigBuilder == null){
			requestConfigBuilder = RequestConfig.custom();
		}
		
		//设置各种超时参数
		requestConfigBuilder
		.setSocketTimeout(socketTimeout)
		.setConnectTimeout(connectTimeout)
		.setConnectionRequestTimeout(ConnectionRequestTimeout);
	}
	
	/**
	 * 设置请求配置创建器
	 * @param requestConfigBuilder
	 */
	public static void setRequestConfigBuilder(Builder requestConfigBuilder) {
		HmHttpClientFactoryHandle.requestConfigBuilder = requestConfigBuilder;
	}

	/**
	 * 设置重试机制
	 * @param httpRequestRetryHandler
	 */
	public static void setHttpRequestRetryHandler(HttpRequestRetryHandler httpRequestRetryHandler) {
		HmHttpClientFactoryHandle.httpRequestRetryHandler = httpRequestRetryHandler;
	}

	/**
	 * 设置http长连接？？
	 * @param connectionKeepAliveStrategy
	 */
	public static void setConnectionKeepAliveStrategy(ConnectionKeepAliveStrategy connectionKeepAliveStrategy) {
		HmHttpClientFactoryHandle.connectionKeepAliveStrategy = connectionKeepAliveStrategy;
	}

	/**
	 * 获取基于链接池的httpclient
	 * @return
	 */
	public static CloseableHttpClient getPoolingHttpClient(){
		//初始化
		init();
		
		if(poolingHttpClientBuilder == null){
			synchronized (HmHttpClientFactoryHandle.class) {
				if(poolingHttpClientBuilder == null){
					poolingHttpClientBuilder = HttpClients.custom();
				}
			}
		}
		
		//设置链接池管理器
		if(poolingHttpClientConnectionManager != null){
			poolingHttpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
		}
		
		
		return fillConfig(poolingHttpClientBuilder).build();
	}
	
	/**
	 * 获取简单的、自定义的、不基于连接池的httpclient
	 * @return
	 */
	public static CloseableHttpClient getSimpleHttpClient(){
		if(simpleHttpClientBuilder == null){
			synchronized (HmHttpClientFactoryHandle.class) {
				if(simpleHttpClientBuilder == null){
					simpleHttpClientBuilder = HttpClients.custom();
				}
			}
		}
		
		return fillConfig(simpleHttpClientBuilder).build();
	}
	
	/**
	 * 获取简单的、缺省的、不基于连接池的httpclient
	 * @return
	 */
	public static CloseableHttpClient getSimpleDefaultHttpClient(){
		return HttpClients.createDefault();
	}
	
	/**
	 * 填充通用的配置到httpclient创建器
	 * @param httpClientBuilder
	 * @return
	 */
	private static HttpClientBuilder fillConfig(HttpClientBuilder httpClientBuilder){
		if(httpClientBuilder == null){
			return httpClientBuilder;
		}
		
		//设置代理
		if(proxies != null && proxies.size()>0){
			Random random = new Random();
			int proxyIndex = random.nextInt(proxies.size());
			httpClientBuilder.setProxy(proxies.get(proxyIndex));
		}
		if(logger.isDebugEnabled()){
			logger.debug("当前设置的代理是：{}",proxies);
		}
		
		//设置请求配置
		if(requestConfigBuilder != null){
			httpClientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
		}
		if(logger.isDebugEnabled()){
			logger.debug("当前设置的request config 是：{}",requestConfigBuilder==null?null:requestConfigBuilder.build());
		}
		
		//设置重试机制
		if(httpRequestRetryHandler != null){
			httpClientBuilder.setRetryHandler(httpRequestRetryHandler);
		}
		if(logger.isDebugEnabled()){
			logger.debug("当前设置的重试机制 是：{}",httpRequestRetryHandler);
		}
		
		//设置http长连接？？
		if(connectionKeepAliveStrategy != null){
			httpClientBuilder.setKeepAliveStrategy(connectionKeepAliveStrategy);
		}
		if(logger.isDebugEnabled()){
			logger.debug("当前设置的connection keep alive strategy 是：{}",connectionKeepAliveStrategy);
		}
		
		return httpClientBuilder;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
